{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Predicciones Privadas con Syft Keras"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 1: Aprendizaje Público\n",
    "\n",
    "Bienvenidos a este tutorial! En los siguientes notebooks aprenderán a cómo proveer predicciones privadas. Por predicciones privadas, nos referimos a que los datos están constantemente encriptados durante todo el proceso. En ningún punto el usuario comparte datos originales, sino mas bien encriptados (es decir, compartidos en secreto). Para proveer estas predicciones privadas, Syft Keras utiliza una librería llamada [TF Encrypted](https://github.com/tf-encrypted/tf-encrypted). TF Encrypted combina estados del arte en técnicas de criptografía y aprendizaje de máquinas, pero no se tienen que preocupar por esto y en su lugar pueden enfocarse en la aplicación de aprendizaje de máquinas.\n",
    "\n",
    "Podemos empezar a proveer predicciones privadas con solo 3 pasos:\n",
    "- **Paso 1**: Entrena tu modelo con Keras normal.\n",
    "- **Paso 2**: Asegura y cuelga tu modelo de aprendizaje de máquinas (servidor).                                               \n",
    "- **Paso 3**: Consulta al modelo seguro para recibir la predicción privada (cliente).\n",
    "\n",
    "Bueno, vamos a seguir estos 3 pasos para que puedan desplegar servicios de aprendizaje de máquinas impactantes sin sacrificar la privacidad del usuario o la seguridad del modelo.\n",
    "\n",
    "Autores:\n",
    "- Jason Mancuso - Twitter: [@jvmancuso](https://twitter.com/jvmancuso)\n",
    "- Yann Dupis - Twitter: [@YannDupis](https://twitter.com/YannDupis)\n",
    "- Morten Dahl - Twitter: [@mortendahlcs](https://github.com/mortendahlcs)\n",
    "\n",
    "Traductores:\n",
    "- Daniel Firebanks-Quevedo - GitHub: [@thefirebanks](https://www.github.com/thefirebanks)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Entrena tu modelo con Keras"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para utilizar técnicas de aprendizaje de máquinas que preservan la privacidad en tus proyectos, no deberías tener que aprender un nuevo framework. Si tienes conocimientos básicos de [Keras](https://keras.io/), puedes empezar usando estas técnicas con Syft Keras. Si nunca antes has utilizado Keras, puedes aprender un poco más en la [documentación](https://keras.io). \n",
    "\n",
    "Antes de proveer predicciones privadas, el primer paso es entrenar tu modelo con la versión normal de Keras. Como un ejemplo, vamos a entrenar un modelo para clasificar dígitos escritos a mano. Para entrenar este modelo usaremos el conjunto de datos canónico de [MNIST](http://yann.lecun.com/exdb/mnist/).\n",
    "\n",
    "Usaremos [este ejemplo](https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py) tomado del repositorio de Keras. Para entrenar tu modelo de clasificación, solo corre la célula siguiente."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "import tensorflow.keras as keras\n",
    "from tensorflow.keras.datasets import mnist\n",
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense, Dropout, Flatten\n",
    "from tensorflow.keras.layers import Conv2D, AveragePooling2D\n",
    "from tensorflow.keras.layers import Activation\n",
    "\n",
    "batch_size = 128\n",
    "num_classes = 10\n",
    "epochs = 2\n",
    "\n",
    "# Dimensiones de la imagen\n",
    "img_rows, img_cols = 28, 28\n",
    "\n",
    "# Dividir los datos en aprendizaje y evaluación\n",
    "(x_train, y_train), (x_test, y_test) = mnist.load_data()\n",
    "\n",
    "x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)\n",
    "x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)\n",
    "input_shape = (img_rows, img_cols, 1)\n",
    "\n",
    "x_train = x_train.astype('float32')\n",
    "x_test = x_test.astype('float32')\n",
    "x_train /= 255\n",
    "x_test /= 255\n",
    "print('x_train shape:', x_train.shape)\n",
    "print(x_train.shape[0], 'train samples')\n",
    "print(x_test.shape[0], 'test samples')\n",
    "\n",
    "# Convertir los vectores de clase a vectores binarios\n",
    "y_train = keras.utils.to_categorical(y_train, num_classes)\n",
    "y_test = keras.utils.to_categorical(y_test, num_classes)\n",
    "\n",
    "model = Sequential()\n",
    "\n",
    "model.add(Conv2D(10, (3, 3), input_shape=input_shape))\n",
    "model.add(AveragePooling2D((2, 2)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Conv2D(32, (3, 3)))\n",
    "model.add(AveragePooling2D((2, 2)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Conv2D(64, (3, 3)))\n",
    "model.add(AveragePooling2D((2, 2)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Flatten())\n",
    "model.add(Dense(num_classes, activation='softmax'))\n",
    "\n",
    "model.compile(loss=keras.losses.categorical_crossentropy,\n",
    "              optimizer=keras.optimizers.Adam(),\n",
    "              metrics=['accuracy'])\n",
    "\n",
    "model.fit(x_train, y_train,\n",
    "          batch_size=batch_size,\n",
    "          epochs=epochs,\n",
    "          verbose=1,\n",
    "          validation_data=(x_test, y_test))\n",
    "score = model.evaluate(x_test, y_test, verbose=0)\n",
    "print('Test loss:', score[0])\n",
    "print('Test accuracy:', score[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Guarda los pesos (weights) para predicciones privadas futuras"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Excelente! Tu modelo ya está entrenado. Vamos a guardar los pesos del modelo con `model.save()`. En el siguiente notebook, vamos a cargar estos pesos en Syft Keras para empezar a proveer predicciones privadas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.save('short-conv-mnist.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
